package servlet;

import config.ActionConfig;
import config.ForwardConfig;
import config.ModuleConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.digester3.Digester;
import org.apache.commons.digester3.binder.DigesterLoader;
import org.apache.commons.digester3.xmlrules.FromXmlRulesModule;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class ActionServlet extends HttpServlet {

    private String configPath;

    private ModuleConfig moduleConfig;

    private Map<String,Object> actions=new HashMap<>();

    @Override
    public void init() throws ServletException {
        System.out.println("ActionServlet.init()");

        configPath=getInitParameter("config");



        Digester digester= DigesterLoader.newLoader(new FromXmlRulesModule() {
            @Override
            protected void loadRules() {
                loadXMLRules(getClass().getClassLoader()
                                       .getResource("config/rule.xml"));
            }
        }).newDigester();

        moduleConfig=new ModuleConfig();
        digester.push(moduleConfig);

        try {
            digester.parse(ActionServlet.class
                                        .getClassLoader()
                                        .getResourceAsStream(configPath));
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServletException("解析"+moduleConfig+"配置文件失败",e);
        }

    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("ActionServlet.service()");

        try {

            //解析请求
            String path = request.getServletPath();


            //将请求扩展名截掉
            path = path.substring(0, path.lastIndexOf("."));

            System.out.println("path = " + path);

            //根据请求查找配置ActionConfig
            ActionConfig actionConfig = moduleConfig.findAction(path);

            System.out.println("actionConfig = " + actionConfig);

            //当请求不存在（没有配置这个请求）时
            if (actionConfig == null) {
                //404
                response.sendError(HttpServletResponse.SC_NOT_FOUND, path + "不存在");
                return;
            }


            System.out.println("type = " + actionConfig.getType());

            System.out.println("method = " + actionConfig.getMethod());

            //根据ActionConfig配置中的type和method调用对应的方法

            //获得配置的Action的Class类型
            Class actionClass = Class.forName(actionConfig.getType());
            //根据Class类型调用无参构造方法创建对象,做成单例提高性能
            Object action=actions.get(actionConfig.getType());
            if(action==null) {
                action = actionClass.newInstance();
                actions.put(actionConfig.getType(),action);
            }
            //获得配置的Action的Method对象
            Method method=actionClass.getMethod(actionConfig.getMethod(),HttpServletRequest.class,HttpServletResponse.class);
            //调用具体的处理者产生数据模型
            String result=(String)method.invoke(action,request,response);

            System.out.println("result = " + result);
            //具体的处理者没有返回任何东西
            if(result==null){
                return;
            }


            //根据result返回的字符串查找对应的ForwardConfig配置
            ForwardConfig forwardConfig=actionConfig.findForward(result);

            System.out.println("forwardConfig = " + forwardConfig);

            System.out.println("path = " + forwardConfig.getPath());


            //如果Action中返回的字符串在配置文件中不存在（没有做forward的配置）
            if(forwardConfig==null){
                response.sendError(HttpServletResponse.SC_NOT_FOUND,result+"没有配置");
                return;
            }


            //访问视图技术
            //根据配置转发或重定向到ForwardConfig中的path
            if(forwardConfig.isRedirect()){
                //重定向到path
                response.sendRedirect(request.getContextPath()+forwardConfig.getPath());
            }else{
                //转发到path
                request.getRequestDispatcher(forwardConfig.getPath()).forward(request,response);
            }


        }catch (Exception e){
            e.printStackTrace();
            throw new ServletException(e);
        }

    }
}






























